#pragma once
#include <iostream>
#include <functional>
#include "acl_cpp/lib_acl.hpp"
#include "socket_session.h"
namespace acl
{
namespace mqtt
{
class socket_session_acceptor
{
public:
	socket_session_acceptor(aio_handle &handle)
		:aio_handle_(handle)
	{
		init();
	}
	bool bind_addr(std::string addr)
	{
		if (sstream->open(addr.c_str()) == false) {
			std::cout << "open " << addr.c_str() 
				<< " error!" << std::endl;
			sstream->close();
			aio_handle_.check();
			return false;
		}
		socket_accept_callback_.bind_socket_accept_callback(
			[this](aio_socket_stream *socket) {
			assert(socket_sess_callback_);
			socket_session session;
			session.bind_aio_socket_stream(socket);
			return socket_sess_callback_(std::move(session));
		});
		sstream->add_accept_callback(&socket_accept_callback_);
		return true;
	}
	template<class SessionCallBackHandler>
	socket_session_acceptor &
		bind_accept_callback(SessionCallBackHandler handler)
	{
		socket_sess_callback_ = handler;
		return *this;
	}
private:
	class socket_accept_callback : public aio_accept_callback
	{
	public:
		socket_accept_callback()
		{

		}
		template <class CallBackHandler>
		socket_accept_callback &
			bind_socket_accept_callback(CallBackHandler callback)
		{
			socket_callback_ = callback;
			return *this;
		}
	private:
		virtual bool accept_callback(aio_socket_stream* client)
		{
			return socket_callback_(client);
		}
		std::function<bool(aio_socket_stream *)> socket_callback_;
	};

	void init()
	{
		sstream = new aio_listen_stream(&aio_handle_);
	}
	socket_accept_callback socket_accept_callback_;
	aio_handle& aio_handle_;
	aio_listen_stream* sstream;
	std::function<bool(socket_session &&)> socket_sess_callback_;
};
}
}
